package EncryptionTools;

public class KeySchedule {
    private static final int[] PC1 = {
            57, 49, 41, 33, 25, 17, 9,
            1, 58, 50, 42, 34, 26, 18,
            10, 2, 59, 51, 43, 35, 27,
            19, 11, 3, 60, 52, 44, 36,
            63, 55, 47, 39, 31, 23, 15,
            7, 62, 54, 46, 38, 30, 22,
            14, 6, 61, 53, 45, 37, 29,
            21, 13, 5, 28, 20, 12, 4
    };
    //Permuted Choice 1

    private static final int[] PC2 = {
            14, 17, 11, 24, 1, 5, 3, 28,
            15, 6, 21, 10, 23, 19, 12, 4,
            26, 8, 16, 7, 27, 20, 13, 2,
            41, 52, 31, 37, 47, 55, 30, 40,
            51, 45, 33, 48, 44, 49, 39, 56,
            34, 53, 46, 42, 50, 36, 29, 32
    };
    //Permuted Choice 2

    private static final int[] SHIFTS = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };

    public static byte[][] generateSubKeys(byte[] key) {
        byte[] key56 = new byte[56];
        byte[][] subKeys = new byte[16][48];

        for (int i = 0; i < PC1.length; i++) {
            key56[i] = key[PC1[i] - 1];
        }
        //Remove 8 bit parity bits

        byte[] C = new byte[28];
        byte[] D = new byte[28];
        System.arraycopy(key56, 0, C, 0, 28);
        System.arraycopy(key56, 28, D, 0, 28);

        for (int round = 0; round < 16; round++) {
            //Shift left
            shiftLeft(C, SHIFTS[round]);
            shiftLeft(D, SHIFTS[round]);

            //Generate sub key according to PC2
            for (int i = 0; i < PC2.length; i++) {
                int index = PC2[i] - 1;
                if (index < 28) {
                    subKeys[round][i] = C[index];
                } else {
                    subKeys[round][i] = D[index - 28];
                }
            }
        }
        return subKeys;
    }

    private static void shiftLeft(byte[] array, int positions) {
        for (int i = 0; i < positions; i++) {
            byte temp = array[0];
            System.arraycopy(array, 1, array, 0, array.length - 1);
            array[array.length - 1] = temp;
        }
    }
}
